/*
 * sqlEditor.cpp
 *
 *  Created on: 28-Oct-2013
 *      Author: vikrantsingh
 */
#include <string>
#include "SqlEditor.h"
#include "../parser/ParseUtil.h"
#include "../sql/QueryDispatcher.h"
#include "../BufferManager/BufferManager.h"
#include "../dependency/QueryStructures.h"
#include "../dependency/ExternDefOfGlobalVariables.h"
#include "../parser.tab.h"
#include "../PageLayout/DBMetaData.h"
#include "../PageLayout/Heap.h"
#include "../PageLayout/Page.h"
#include "../PageLayout/DataPage.h"
#include "../Utils/Timer.h"

SqlEditor::SqlEditor() {
    // TODO Auto-generated constructor stub

}

SqlEditor::~SqlEditor() {
    // TODO Auto-generated destructor stub
}

STATUS_CODE SqlEditor::showEditor() {
    //query
    //	string buff =			"CREATE TABLE1 HELLO(col_one INTEGER,col_two VARCHAR(100), col_3 INTEGER)";
    //parse
    //	ParseUtil p;
    //	p.parseQuery(buff);
    //
    //	cout << "tab:" << executeStructures->schema.tableName;

    //cout<<"err:"<<executeStructures->errorMessage;

    //operate
    //	ExecuteManager em;
    //	em.execute(executeStructures);
    //////////////////////
    int testOn = 0;

    if (testOn == 1) {
        //        char buffer[2000];
        //        FILE *fp = fopen("");
        std::ifstream file("Test/test.sql");
        std::string query;
        while (std::getline(file, query)) {
            // Process str

            //string query = "CREATE DATABASE HEL;"
            cout << "\n Runing =>" << query << endl;
            ParseUtil p;
            p.parseQuery(query);
            //operate
            QueryDispatcher em;
            int err = em.run(queryStruct);
            if (err != SUCCESS) {
                cout << "\nSorry Error Occurred :"
                        << queryStruct->errorMessage;
            }
        }
        cout << "\n *** CHEERS! EVERYTHING WORKS FINE!!!";

    } else {

        string query;
        while (true) {
            query = "";

            cout << endl << "SQL#";

            do {
                string subq;
                cin >> subq;
                if (query.length() > 0)
                    query.append(" ");
                query.append(subq);

            } while (query[query.length() - 1] != ';');

            //		DEBUG("QUERY:"<<query);
            query.resize(query.length() - 1);

            if (strcmp(query.c_str(), "exit") == 0
                    || strcmp(query.c_str(), "EXIT") == 0) {


                cout << endl << "exiting sql editor, bye!" << endl;
                break;
            } else if (strcmp(query.c_str(), "test") == 0
                    || strcmp(query.c_str(), "TEST") == 0) {
                testing();
            } else {

                Timer start;
                start.startTimer();
                ParseUtil p;
                p.parseQuery(query);
                //operate
                QueryDispatcher em;
                int err = em.run(queryStruct);
                if (err != SUCCESS) {
                    cout << "\nSorry Error Occurred :"
                            << queryStruct->errorMessage;
                }
                start.endTimer();

            }

        }

    }
    return SUCCESS;
    ;
}

STATUS_CODE SqlEditor::testing() {
    string query;
    while (true) {
        query = "";
        cout << endl << "SQL-TEST#";
        do {
            string subq;
            cin >> subq;
            if (query.length() > 0)
                query.append(" ");
            query.append(subq);

        } while (query[query.length() - 1] != ';');

        query.resize(query.length() - 1);



        DEBUG("QUERY:" << query);

        if ((query.compare("EXIT") == 0)
                || (query.compare("exit ") == 0)) {
            cout << endl << "exiting SQL TEST, bye!" << endl;
            break;
        } else {
            int err = executeTest(query);
            if (err != SUCCESS) {
                cout << "\nSorry Error Occurred :";
            }

        }

    }
    return SUCCESS;

}

STATUS_CODE SqlEditor::executeTest(string query) {
    stringstream ss(query);
    string buf;
    vector < string > tokens;
    while (ss >> buf)
        tokens.push_back(buf);
    if (tokens.size() == 0) return FAILURE;
    string command = tokens[0];
    //cout << command << ":" << endl;
    if (command.compare("PARSER") == 0) {
        cout << "Enter Query \n";
        query = "";

        do {
            string subq;
            cin >> subq;
            if (query.length() > 0)
                query.append(" ");
            query.append(subq);

        } while (query[query.length() - 1] != ';');

        //		DEBUG("QUERY:"<<query);
        query.resize(query.length() - 1);

        ParseUtil p;
        p.parseQuery(query);
        //operate
        cout << queryStruct->toString();
    } else if (command.compare("RUN") == 0) {
        
        string filename="test.sql";
        if (tokens.size() == 2)
            filename=tokens[1];
        string filepath="Test/";
        filepath.append(filename);    
        std::ifstream file(filepath.c_str());
        std::string query;
        
        Timer time;
        time.startTimer();


        while (std::getline(file, query)) {
            // Process str

            if (query[0] == '-' && query[1] == '-')
                continue;

            //string query = "CREATE DATABASE HEL;"
//            cout << "\n Runing =>" << query << endl;
            ParseUtil p;
            p.parseQuery(query);
            //operate
            QueryDispatcher em;
            int err = em.run(queryStruct);
            if (err != SUCCESS) {
                cout << "\nSorry Error Occurred :"
                        << queryStruct->errorMessage;
            }
        }
        time.endTimer();
        cout << "\n *** SCRIPT EXECUTED COMPLETELY !!!";
    } else if (command.compare("METADATA") == 0) {
        DBMetaData main(0);
        cout << main.toString();

    } else if (command.compare("DIRHEADER") == 0) {
        DirHeader dh(Util::string_to_int(tokens[1]));
        cout << "\n===================DIR HEADER===================\n" << dh.toString();

    } else if (command.compare("DIRPAGE") == 0) {
        DirectoryPage dp(Util::string_to_int(tokens[1]));
        cout << "\n===================DIR PAGE===================\n" << dp.toString();


    } else if (command.compare("DATAPAGE") == 0) {

        DataPage dataPg(Util::string_to_int(tokens[1]));
        cout << "\n===================DATA PAGE===================\n" << dataPg.toString();

    } else if (command.compare("PAGE") == 0) {
        int pgNo = Util::string_to_int(tokens[1]);
        Page pg(pgNo);
        cout << "\n===================PAGE HEADER===================\n" << pg._pgHead.toString();

    } else {
        cout << "Invalid Cammand.. press help for seeing commands.." << endl;
    }
    return SUCCESS;

}